package kubayaxi.video.client.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.netty.util.concurrent.CompleteFuture;
import jodd.cli.Cli;
import kubayaxi.video.client.service.IClientUserService;
import kubayaxi.video.mybatis.auto.dao.*;
import kubayaxi.video.mybatis.auto.model.*;
import kubayaxi.video.mybatis.customize.dao.ClientUserMeMapper;
import kubayaxi.video.mybatis.customize.model.user.dto.*;
import kubayaxi.video.mybatis.customize.model.user.vo.*;
import kubayaxi.video.service.base.common.enums.DeleteEnum;
import kubayaxi.video.service.base.common.enums.FollowStatusEnum;
import kubayaxi.video.service.base.common.exception.KubayaxiException;
import kubayaxi.video.service.base.common.request.BaseRequest;
import kubayaxi.video.service.base.common.treadlocal.UserContent;
import kubayaxi.video.service.base.common.vo.CommonPageResult;
import kubayaxi.video.service.base.util.common.Asserts;
import kubayaxi.video.service.base.util.transaction.TransactionUtil;
import org.apache.catalina.User;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@Service
public class ClientUserServiceImpl implements IClientUserService {

    @Resource
    private ClientUserMeMapper clientUserMeMapper;
    @Resource
    private FollowRelativeMapper followRelativeMapper;
    @Resource
    private ClientUserMapper clientUserMapper;
    @Resource
    private CommentMapper commentMapper;
    @Resource
    private LikeRecordMapper likeRecordMapper;
    @Resource
    private VideoMapper videoMapper;
    @Resource
    private HistoryRecordMapper historyRecordMapper;
    @Resource
    private TransactionUtil transactionUtil;

    /**
     * 获取历史记录列表
     */
    @Override
    public CommonPageResult<GetVideoRecordListVO> getVideoRecordList(BaseRequest dto) {
        Long userId = UserContent.get();
        Page page = new Page(dto.getPageNo(),dto.getPageSize());
        IPage<GetVideoRecordListVO> list = clientUserMeMapper.getVideoRecordList(page, userId);
        CommonPageResult<GetVideoRecordListVO> ans = new CommonPageResult<>();
        ans.setList(list.getRecords());
        ans.setTotal(list.getTotal());
        return ans;
    }

    /**
     * 获取关注者或者粉丝列表
     */
    @Override
    public List<GetFollowVO> getFollow(BaseRequest<GetFollowDTO> dto) {
        GetFollowDTO data = dto.getData();
        Asserts.isNotNull(data.getQueryType(),"查询状态为空");
        Long userId = UserContent.get();
        if (data.getQueryType() != 51 && data.getQueryType() != 52) throw new KubayaxiException("查询类型错误");
        if (data.getQueryType() == 51){
            List<FollowRelative> list = followRelativeMapper.selectList(new LambdaQueryWrapper<FollowRelative>()
                    .eq(FollowRelative::getUId, userId)
                    .eq(FollowRelative::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                    .orderByDesc(FollowRelative::getCreatedTime)
                    .last("limit " + data.getNum()));
            return list.stream().map(item -> {
                ClientUser beClientUser = clientUserMapper.selectById(item.getBeuId());
                GetFollowVO getFollowVO = new GetFollowVO();
                getFollowVO.setUId(beClientUser.getId());
                getFollowVO.setNickName(beClientUser.getNickName());
                getFollowVO.setPortraitUrl(beClientUser.getPortraitUrl());
                getFollowVO.setFollowStatus(FollowStatusEnum.FOLLOWED.getCode());
                return getFollowVO;
            }).collect(Collectors.toList());
        } else {
            List<FollowRelative> list = followRelativeMapper.selectList(new LambdaQueryWrapper<FollowRelative>()
                    .eq(FollowRelative::getBeuId, userId)
                    .eq(FollowRelative::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                    .orderByDesc(FollowRelative::getCreatedTime));
            return list.stream().map(item -> {
                ClientUser beClientUser = clientUserMapper.selectById(item.getUId());
                GetFollowVO getFollowVO = new GetFollowVO();
                getFollowVO.setUId(beClientUser.getId());
                getFollowVO.setNickName(beClientUser.getNickName());
                getFollowVO.setPortraitUrl(beClientUser.getPortraitUrl());
                FollowRelative followRelative = followRelativeMapper.selectOne(new LambdaQueryWrapper<FollowRelative>().eq(FollowRelative::getUId, userId).eq(FollowRelative::getBeuId, beClientUser.getId()).eq(FollowRelative::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
                getFollowVO.setFollowStatus(ObjectUtil.isNotNull(followRelative) ? FollowStatusEnum.FOLLOWED.getCode() : FollowStatusEnum.NO_FOLLOW.getCode());
                return getFollowVO;
            }).collect(Collectors.toList());
        }

    }

    /**
     * 获取用户关注者的动态列表
     */
    @Override
    public CommonPageResult<GetDynamicListVO> getDynamicList(BaseRequest dto) {
        Page page = new Page(dto.getPageNo(),dto.getPageSize());
        IPage<GetDynamicListVO> list = clientUserMeMapper.getDynamicList(page, UserContent.get());
        CommonPageResult<GetDynamicListVO> ans = new CommonPageResult<>();
        ans.setList(list.getRecords());
        ans.setTotal(list.getTotal());
        return ans;
    }

    /**
     * 获取当前用户详细信息
     */
    @Override
    public GetUserInfoVO getUserInfo() {
        Long uId = UserContent.get();
        return getPriUserInfo(uId);
    }

    /**
     * 获取用户详细信息
     */
    @Override
    public GetUserInfoVO getUserInfo2(BaseRequest<GetUserInfo2DTO> dto) {
        GetUserInfo2DTO data = dto.getData();
        Asserts.isNotNull(data.getUId(),"用户id为空");
        return getPriUserInfo(data.getUId());
    }

    /**
     * 修改个人信息
     */
    @Override
    public void updateInfo(BaseRequest<UpdateInfoDTO> dto) {
        UpdateInfoDTO data = dto.getData();
        Asserts.isNotBlank(data.getPortraitUrl(),"头像地址为空");
        Asserts.isNotBlank(data.getNickName(),"昵称为空");
        Asserts.isTrue(ObjectUtil.isNotNull(data.getSex()),"性别为空");
        Asserts.isNotBlank(data.getDesc(),"简介为空");
        Long uId = UserContent.get();
        int update = clientUserMapper.update(null, new LambdaUpdateWrapper<ClientUser>()
                .eq(ClientUser::getId, uId)
                .set(ClientUser::getPortraitUrl, data.getPortraitUrl())
                .set(ClientUser::getNickName, data.getNickName())
                .set(ClientUser::getSex, data.getSex())
                .set(ClientUser::getDesc, data.getDesc()));
        Asserts.isTrue(update == 1,"更新失败");
    }

    private GetUserInfoVO getPriUserInfo(Long uId){
        ClientUser clientUser = clientUserMapper.selectById(uId);
        GetUserInfoVO ans = new GetUserInfoVO();
        ans.setDesc(clientUser.getDesc());
        ans.setNickName(clientUser.getNickName());
        ans.setPortraitUrl(clientUser.getPortraitUrl());
        ans.setUId(clientUser.getId());
        ans.setDynamicNum(clientUser.getDynamicNum());
        ans.setFollowNum(clientUser.getFollowNum());
        ans.setFanNum(clientUser.getFanNum());
        ans.setSex(clientUser.getSex());
        ans.setPhone(clientUser.getPhone());
        return ans;
    }

    /**
     * 获取用户我的喜欢列表
     */
    @Override
    public CommonPageResult<GetUserLikeListVO> getUserLikeList(BaseRequest dto) {
        Page<LikeRecord> page = new Page(dto.getPageNo(),dto.getPageSize());
        Long uId = UserContent.get();
        IPage<GetUserLikeListVO> list = clientUserMeMapper.getUserLikeList(page, uId);
        CommonPageResult<GetUserLikeListVO> ans = new CommonPageResult<>();
        ans.setTotal(list.getTotal());
        ans.setList(list.getRecords());
        return ans;
    }

    /**
     * 获取我的发布列表
     */
    @Override
    public CommonPageResult<GetMyPublishListVO> getMyPublishList(BaseRequest dto) {
        Long uId = UserContent.get();
        Page page = new Page(dto.getPageNo(), dto.getPageSize());
        IPage<GetMyPublishListVO> list = clientUserMeMapper.getMyPublishList(page, uId);
        CommonPageResult<GetMyPublishListVO> ans = new CommonPageResult<>();
        ans.setTotal(list.getTotal());
        ans.setList(list.getRecords());
        return ans;
    }

    /**
     * 获取我的消息
     */
    @Override
    public List<MyMessageVO> myMessage() {
        Long uId = UserContent.get();
        ClientUser user = clientUserMapper.selectById(uId);
        List<MyMessageVO> ans = new ArrayList<>();
        //用4个线程同时查找数据
        //查评论
        CompletableFuture<List<MyMessageVO>> commentFuture = CompletableFuture.supplyAsync(() -> {
            List<Long> collectIds = commentMapper.selectList(new LambdaQueryWrapper<Comment>()
                            .eq(Comment::getUId, uId)
                            .eq(Comment::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()))
                    .stream().map(Comment::getId).collect(Collectors.toList());
            List<Comment> commentList = commentMapper.selectList(new LambdaQueryWrapper<Comment>()
                    .in(Comment::getPId, collectIds)
                    .eq(Comment::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
            List<MyMessageVO> commentColl = commentList.stream().map(item -> {
                Video video = videoMapper.selectById(item.getVId());
                return MyMessageVO.builder()
                        .type(71)
                        .uId(item.getUId())
                        .nickName(item.getNickName())
                        .portraitUrl(item.getPortraitUrl())
                        .content(item.getContent())
                        .vId(item.getVId())
                        .title(video.getTitle())
                        .createdTime(item.getCreatedTime())
                        .build();
            }).collect(Collectors.toList());
            return commentColl;
        });

        //查我发布的视频
        CompletableFuture<List<MyMessageVO>> videoFuture = CompletableFuture.supplyAsync(() -> {
            List<Video> videoList = videoMapper.selectList(new LambdaQueryWrapper<Video>()
                    .eq(Video::getUId, uId)
                    .eq(Video::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
            List<MyMessageVO> videoColl = videoList.stream().map((item) -> MyMessageVO.builder()
                    .type(74)
                    .uId(uId)
                    .nickName(user.getNickName())
                    .portraitUrl(user.getPortraitUrl())
                    .vId(item.getId())
                    .title(item.getTitle())
                    .createdTime(item.getCreatedTime())
                    .build()).collect(Collectors.toList());
            return videoColl;
        });

        //查点赞,我发布了哪些视频,用户点赞的视频是其中一个
        CompletableFuture<List<MyMessageVO>> likeFutrue = CompletableFuture.supplyAsync(() -> {
            List<Video> videoList = videoMapper.selectList(new LambdaQueryWrapper<Video>()
                    .eq(Video::getUId, uId)
                    .eq(Video::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
            List<Long> videoForLike = videoList.stream().map(Video::getId).collect(Collectors.toList());
            List<LikeRecord> likeRecordList = likeRecordMapper.selectList(new LambdaQueryWrapper<LikeRecord>()
                    .in(LikeRecord::getVId, videoForLike)
                    .eq(LikeRecord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
            List<MyMessageVO> likeColl = likeRecordList.stream().map(item -> {
                ClientUser clientUser = clientUserMapper.selectById(item.getUId());
                Video video = videoMapper.selectById(item.getVId());
                return MyMessageVO.builder()
                        .type(72)
                        .uId(item.getUId())
                        .nickName(clientUser.getNickName())
                        .portraitUrl(clientUser.getPortraitUrl())
                        .vId(item.getVId())
                        .title(video.getTitle())
                        .createdTime(item.getCreatedTime())
                        .build();
            }).collect(Collectors.toList());
            return likeColl;
        });

        //查关注
        CompletableFuture<List<MyMessageVO>> follFutrue = CompletableFuture.supplyAsync(() -> {
            List<FollowRelative> followRelativeList = followRelativeMapper.selectList(new LambdaQueryWrapper<FollowRelative>()
                    .eq(FollowRelative::getBeuId, uId)
                    .eq(FollowRelative::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
            List<MyMessageVO> followColl = followRelativeList.stream().map(item -> {
                ClientUser clientUser = clientUserMapper.selectById(item.getUId());
                return MyMessageVO.builder()
                        .type(73)
                        .uId(item.getUId())
                        .nickName(clientUser.getNickName())
                        .portraitUrl(clientUser.getPortraitUrl())
                        .createdTime(item.getCreatedTime())
                        .build();
            }).collect(Collectors.toList());
            return followColl;
        });

        //把四个list合在一起,根据创建时间倒序排序
        try{
            ans.addAll(commentFuture.get());
            ans.addAll(likeFutrue.get());
            ans.addAll(follFutrue.get());
            ans.addAll(videoFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        ans.sort((o1, o2) -> o2.getCreatedTime().compareTo(o1.getCreatedTime()));
        return ans;
    }

    /**
     * 删除历史记录
     */
    @Override
    public void deleteHistory(BaseRequest<DeleteHistoryDTO> dto) {
        DeleteHistoryDTO data = dto.getData();
        Long uId = UserContent.get();
        boolean b = transactionUtil.transactional(() -> {
            int delete = historyRecordMapper.update(null, new LambdaUpdateWrapper<HistoryRecord>()
                    .in(HistoryRecord::getVId, data.getVideoIds())
                    .eq(HistoryRecord::getUId, uId)
                    .set(HistoryRecord::getDeleteStatus, DeleteEnum.DELETED.getCode()));
            return delete == data.getVideoIds().size();
        });
        Asserts.isTrue(b,"删除历史记录失败");
    }

    /**
     * 删除我的喜欢
     */
    @Override
    public void deleteLike(BaseRequest<DeleteLikeDTO> dto) {
        DeleteLikeDTO data = dto.getData();
        Long uId = UserContent.get();
        //删除喜欢记录表,更新视频表
        boolean b = transactionUtil.transactional(() -> {
            List<Long> videoIds = data.getVideoIds();
            int delete = likeRecordMapper.delete(new LambdaUpdateWrapper<LikeRecord>()
                    .in(LikeRecord::getVId, videoIds)
                    .eq(LikeRecord::getUId, uId)
                    .eq(LikeRecord::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
            for (Long videoId : videoIds) {
                int update = videoMapper.update(null, new LambdaUpdateWrapper<Video>()
                        .eq(Video::getId, videoId)
                        .eq(Video::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode())
                        .setSql("like_num = like_num - 1"));
                if (update != 1) return false;
            }
            return delete == videoIds.size();
        });
        Asserts.isTrue(b,"删除喜欢记录失败");
    }
}
